package stack

import (
	"go_gvm_mini/instructions/base"
	"go_gvm_mini/rtda"
)

// dup  复制栈顶数值并将复制值压入栈顶
//dup_x1 复制操作数栈顶的值,并插入栈顶一下的两个值  <=> 原样+复制栈顶的值并入栈
//dup_x2 复制栈顶数值并将三个(或两个)复制值压入栈顶
//dup2 复制栈顶一个(对于long或double类型)或两个(对于非long或double的其他类型)数值并将复制值压入栈顶
//dup2_x1 dup_x1指令的双倍版本
//dup2_x2 dup_x2指令的双倍版本

type DUP struct {
	base.NoOperandsInstruction
}

func (self *DUP) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	v1 := stack.PopSlot()
	stack.PushSlot(v1)

	stack.PushSlot(v1)
}

type DUP_X1 struct {
	base.NoOperandsInstruction
}

func (self *DUP_X1) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	v1 := stack.PopSlot()
	v2 := stack.PopSlot()
	stack.PushSlot(v1)
	stack.PushSlot(v2)

	stack.PushSlot(v1)
}

type DUP_X2 struct {
	base.NoOperandsInstruction
}

func (self *DUP_X2) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	v1 := stack.PopSlot()
	v2 := stack.PopSlot()
	v3 := stack.PopSlot()
	stack.PushSlot(v1)
	stack.PushSlot(v3)
	stack.PushSlot(v2)

	stack.PushSlot(v1)
}

type DUP2 struct {
	base.NoOperandsInstruction
}

func (self *DUP2) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	v1 := stack.PopSlot()
	v2 := stack.PopSlot()
	stack.PushSlot(v2)
	stack.PushSlot(v1)

	stack.PushSlot(v2)
	stack.PushSlot(v1)
}

type DUP2_X1 struct {
	base.NoOperandsInstruction
}

func (self *DUP2_X1) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	v1 := stack.PopSlot()
	v2 := stack.PopSlot()
	v3 := stack.PopSlot()
	stack.PushSlot(v2)
	stack.PushSlot(v1)

	stack.PushSlot(v3)
	stack.PushSlot(v2)
	stack.PushSlot(v1)
}

type DUP2_X2 struct {
	base.NoOperandsInstruction
}

func (self *DUP2_X2) Execute(jFrame *rtda.JFrame) {
	stack := jFrame.OperandStack()
	v1 := stack.PopSlot()
	v2 := stack.PopSlot()
	v3 := stack.PopSlot()
	v4 := stack.PopSlot()
	stack.PushSlot(v2)
	stack.PushSlot(v1)
	stack.PushSlot(v4)
	stack.PushSlot(v3)
	stack.PushSlot(v2)
	stack.PushSlot(v1)
}
